package cn.jantd.modules.activiti.command;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;

/**
 *
 */
public class RejectToAnyWhereTaskCmd implements Command<Void> {
    protected String executionId;
    protected ActivityImpl desActivity;
    protected Map<String, Object> paramvar;
    protected ActivityImpl currentActivity;
    protected ReadOnlyProcessDefinition processDefinitionEntity;
    /**
     */
    public Void execute(CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = Context
                .getCommandContext().getExecutionEntityManager();
        // 获取当前流程的executionId，因为在并发的情况下executionId是唯一的。
        ExecutionEntity executionEntity = executionEntityManager
                .findExecutionById(executionId);
        executionEntity.setVariables(paramvar);
        executionEntity.setEventSource(this.currentActivity);
        executionEntity.setActivity(this.currentActivity);

        List<ExecutionEntity> executionEntitys = executionEntityManager.findChildExecutionsByParentExecutionId(executionEntity.getParentId());
        if(!executionEntitys.isEmpty()){
            String executionParentId = executionEntity.getParentId();
            for(ExecutionEntity execution : executionEntitys){
                // 根据executionId 获取Task
                Iterator<TaskEntity> localIterator = Context.getCommandContext()
                        .getTaskEntityManager()
                        .findTasksByExecutionId(execution.getId()).iterator();

                while (localIterator.hasNext()) {
                    TaskEntity taskEntity = (TaskEntity) localIterator.next();
                    // 触发任务监听
                    taskEntity.fireEvent(TaskListener.EVENTNAME_COMPLETE);
                    // 删除任务的原因
                    Context.getCommandContext().getTaskEntityManager()
                            .deleteTask(taskEntity, TaskEntity.DELETE_REASON_COMPLETED, false);
                }
                execution.remove();
            }

            ExecutionEntity parentExecutionEntity = executionEntityManager
                    .findExecutionById(executionParentId);
            ActivityImpl pActivityImpl = (ActivityImpl) this.processDefinitionEntity.findActivity(parentExecutionEntity.getActivityId());
            executionEntity.setVariables(paramvar);
            executionEntity.setEventSource(pActivityImpl);
            executionEntity.setActivity(pActivityImpl);
            parentExecutionEntity.executeActivity(this.desActivity);

        }else{
            // 根据executionId 获取Task
            Iterator<TaskEntity> localIterator = Context.getCommandContext()
                    .getTaskEntityManager()
                    .findTasksByExecutionId(this.executionId).iterator();

            while (localIterator.hasNext()) {
                TaskEntity taskEntity = (TaskEntity) localIterator.next();
                // 触发任务监听
                taskEntity.fireEvent("complete");
                // 删除任务的原因
                Context.getCommandContext().getTaskEntityManager()
                        .deleteTask(taskEntity, "completed", false);
            }
            executionEntity.executeActivity(this.desActivity);
        }
        return null;
    }

    /**
     *
     * @param executionId
     * @param desActivity
     * @param paramvar
     * @param currentActivity
     */
    public RejectToAnyWhereTaskCmd(String executionId, ActivityImpl desActivity,
                                   Map<String, Object> paramvar, ActivityImpl currentActivity,
                                   ReadOnlyProcessDefinition processDefinitionEntity) {
        this.executionId = executionId;
        this.desActivity = desActivity;
        this.paramvar = paramvar;
        this.currentActivity = currentActivity;
        this.processDefinitionEntity = processDefinitionEntity;
    }
}
